<template>
  <div class="tree-container">
    <el-row class="mb5 header" type="flex" justify="space-between">
      <el-col :span="18">
        <span class="title">{{ title }}</span>
      </el-col>
      <el-col :span="1.5">
        <el-button class="button" @click="handleCreateType">{{ addButtonText }}</el-button>
      </el-col>
    </el-row>
    <span v-if="show" style="display: flex; align-items: center;">
      <el-input v-model="inputValue" :maxlength="maxlength" style="margin: 5px 0;" :placeholder="placeholder" />
      <i class="el-icon-check icon" @click="inputConfirm" />
      <i class="el-icon-close icon" @click="inputCancel" />
    </span>
    <el-tree
      ref="tree"
      v-loading="loading"
      v-bind="$attrs"
      node-key="id"
      :highlight-current="highlight"
      :default-expanded-keys="defaultExpandedKeys"
      default-expand-all
      :accordion="true"
      :data="treeList"
      :props="propsOption"
      :expand-on-click-node="false"
      v-on="$listeners"
      @node-click="handleNodeClick"
    >
      <span slot-scope="{ node, data }" class="custom-tree-node">
        <el-tooltip v-if="!data.editable" class="item" effect="light" :disabled="node.label.length < 6" :content="node.label" placement="top">
          <span class="label">{{ node.label }}</span>
        </el-tooltip>
        <el-input v-else v-model="data.inputValue" :maxlength="maxlength" />
        <span class="icon">
          <i v-if="!data.editable" class="el-icon-edit-outline" @click.stop="handleEdit(node, data)" />
          <i v-if="!data.editable" class="el-icon-plus" @click.stop="handleAdd(node, data)" />
          <el-popconfirm confirm-button-text="确定" cancel-button-text="取消" icon="el-icon-info" icon-color="#51abab" :title="`确定删除${data[propsOption.label]}吗？`" @onConfirm="handleDelete(node, data)">
            <i v-if="!data.editable" slot="reference" class="el-icon-delete" @click="stopPropagation" />
          </el-popconfirm>
          <i v-if="data.editable" class="el-icon-check" @click.stop="handleConfirm(node, data)" />
          <i v-if="data.editable" class="el-icon-close" @click.stop="handleCancel(node, data)" />
        </span>
      </span>
    </el-tree>
  </div>
</template>
<script>
import { request } from "@rabbit.do/rabbit";

export default {
  name: 'EditableTree',
  props: {
    title: {
      type: String,
      default: '组件分类',
    },
    addButtonText: {
      type: String,
      default: '新增分类',
    },
    maxlength: {
      type: [String, Number],
      default: 10,
    },
    propsOption: {
      type: Object,
      default: () => {
        return {
          children: 'childList',
          label: 'name',
        };
      },
    },
    placeholder: {
      type: String,
      default: '请输入分类名称',
    },
    dataApi: {
      type: Object,
      required: true,
      default: () => ({
        url: '',
        params: {},
      }),
    },
    createApi: {
      type: String,
      required: true,
    },
    createProps: {
      type: Object,
      default: () => ({
        parentId: 'parentId',
        name: 'inputValue',
      }),
    },
    updateApi: {
      type: String,
      required: true,
    },
    updateProps: {
      type: Object,
      default: () => ({
        id: 'id',
        name: 'inputValue',
      }),
    },
    deleteApi: {
      type: String,
      required: true,
    },
    deleteProps: {
      type: Object,
      default: () => ({
        id: 'id',
      }),
    },
    refreshAfterRequest: {
      type: Boolean,
      default: true,
    },
    createSuccessText: {
      type: String,
      default: '新增成功',
    },
    updateSuccessText: {
      type: String,
      default: '更新成功',
    },
    deleteSuccessText: {
      type: String,
      default: '删除成功',
    },
    type: {
      type: Number,
      default: 0,
    },
  },
  data() {
    return {
      inputValue: '',
      treeList: [],
      show: false,
      loading: false,
      defaultExpandedKeys: [],
      highlight: true,
    };
  },
  mounted() {
    this.getTree();
  },
  methods: {
    async getTree() {
      this.loading = true;
      const res = await request({ url: this.dataApi.url, data: { ...this.dataApi.params }}).finally(() => (this.loading = false));
      if (res.statusCode !== 600) return;
      this.$emit('data-callback', res);
      this.treeList = res.data;
    },
    handleNodeClick(data, node) {
      if (data.highlight) {
        this.highlight = false;
        this.$emit('nodeClick', {});
        this.$set(data, 'highlight', false);
      } else {
        this.highlight = true;
        this.$emit('nodeClick', data);
        this.$set(data, 'highlight', true);
      }
    },
    handleCreateType() {
      this.show = true;
    },
    handleProps(props, target) {
      const obj = {};
      Object.entries(props).forEach(item => {
        obj[item[0]] = target[item[1]];
      });
      return obj;
    },
    inputCancel() {
      this.show = false;
    },
    async inputConfirm() {
      if (!this.inputValue) return this.msgError('请输入内容');
      const res = await request({ url: this.createApi, 'data': { parentId: '', [this.propsOption.label]: this.inputValue, type: this.type ? this.type : undefined }});
      if (res.statusCode !== 600) return;
      this.show = false;
      this.msgSuccess(this.createSuccessText);
      if (this.refreshAfterRequest) this.getTree();
    },
    // async handleInputFocus() {
    //   if (!this.inputValue) {
    //     this.show = false;
    //   } else {
    //     const res = request({ url: this.createApi, 'data': { parentId: '', [this.propsOption.label]: this.inputValue, type: this.type ? this.type : undefined }});
    //     if (res.statusCode !== 600) return;
    //     this.$emit('success', 'create');
    //     this.msgSuccess(this.createSuccessText);
    //     if (this.refreshAfterRequest) this.getTree();
    //   }
    // },
    handleEdit(node, data) {
      this.$set(data, 'inputValue', data[this.propsOption.label]);
      this.$set(data, 'editable', true);
    },
    handleAdd(node, data) {
      this.defaultExpandedKeys = [data.id];
      const key = this.propsOption.children;
      const child = { [key]: [], editable: true, isAdd: true, parentId: data.id };
      if (!data[key]) {
        this.$set(data, [key], []);
      }
      data[key].unshift(child);
    },
    async handleDelete(node, data) {
      const res = await request({ url: this.deleteApi, 'data': this.handleProps(this.deleteProps, data) });
      if (res.statusCode !== 600) return;
      this.msgSuccess(this.deleteSuccessText);
      if (this.refreshAfterRequest) this.getTree();
    },
    async handleConfirm(node, data) {
      const key = this.propsOption.label;
      if (data.isAdd) {
        if (!data.inputValue) return this.msgError("输入框不能为空");
        const res = await request({ url: this.createApi, data: { ...this.handleProps(this.createProps, data), type: this.type ? this.type : undefined }});
        if (res.statusCode !== 600) return;
        this.msgSuccess(this.createSuccessText);
        if (this.refreshAfterRequest) this.getTree();
      } else {
        if (data.inputValue === data[key]) return this.$set(data, 'editable', false);
        const res = await request({ url: this.updateApi, data: this.handleProps(this.updateProps, data) });
        if (res.statusCode !== 600) return;
        this.msgSuccess(this.updateSuccessText);
        if (this.refreshAfterRequest) this.getTree();
      }
    },
    handleCancel(node, data) {
      if (data.isAdd) {
        if (!data[this.propsOption.label]) {
          const index = node.parent.data[this.propsOption.children].findIndex(item => item.parentId === data.parentId);
          node.parent.data[this.propsOption.children].splice(index, 1);
        }
      } else {
        this.$set(data, 'editable', false);
      }
    },
    refresh() {
      this.getTree();
    },
    stopPropagation(e) {
      e.stopPropagation();
    },
  },
};
</script>
<style lang="scss" scoped>
@import "~@/assets/styles/variables";
@import "~@/assets/styles/mixin";

.tree-container {
  margin: 10px 0;
  min-width: 300px;
  font-size: 14px;
}
.header {
  display: flex;
  align-items: center;
  padding: 0 5px;
  .title {
    font-weight: 400;
    line-height: 14px;
    color: #333333;
    font-size: 18px;
  }
  .button {
    height: 2.5em;
    font-size: 12px;
    background-color: $text-color !important;
  }
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  // font-size: 12px;
  padding-right: 8px;
  &:hover > .icon {
    display: block;
  }
  .label{
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space:nowrap;
  }
}
/deep/.el-input__inner {
  height: 22px;
  line-height: 1;
  margin-right: 5px;
  font-size: inherit;
}
.icon {
  // display: none;
  // position: absolute;
  // right: 5px;
  color: $text-color;
  cursor: pointer;
  @include disabledUserSelect;
}
</style>
